package org.stvd.service.workflow.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.javax.el.ExpressionFactory;
import org.activiti.engine.impl.javax.el.ValueExpression;
import org.activiti.engine.impl.juel.ExpressionFactoryImpl;
import org.activiti.engine.impl.juel.SimpleContext;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.stvd.core.util.LogUtil;
import org.stvd.core.util.StringUtil;
import org.stvd.service.workflow.ProcessCoreService;

/**
 * 流程操作核心类<br>
 * 此核心类主要处理：流程通过、驳回、会签、转办、中止、挂起等核心操作<br>
 * 
 * @author wangfuwei
 */
@Service("ProcessCoreService")
public class ProcessCoreServiceImpl implements ProcessCoreService {

	@Autowired
	protected RepositoryService repositoryService;

	@Autowired
	protected RuntimeService runtimeService;

	@Autowired
	protected TaskService taskService;

	@Autowired
	protected FormService formService;

	@Autowired
	protected HistoryService historyService;

	public ProcessInstance startInstanceByKey(String processDefinitionKey, String businessKey,
			Map<String, Object> variables) {
		return runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
	}

	public boolean deleteProcessInstanceById(String processInstanceId, String deleteReason) {
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		if (processInstance == null) {
			return false;
		} else {
			runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
			return true;
		}
	}

	public List<ActivityImpl> findBackAvtivity(String taskId) throws Exception {
		List<ActivityImpl> rtnList = null;
		if (isJointTask(taskId)) {// 会签任务节点，不允许驳回
			rtnList = new ArrayList<ActivityImpl>();
		} else {
			rtnList = iteratorBackActivity(findProcessInstanceByTaskId(taskId), taskId, findActivitiImpl(taskId, null),
					new ArrayList<ActivityImpl>(), new ArrayList<ActivityImpl>());
		}
		return reverList(rtnList);
	}

	public List<ActivityImpl> findBackAvtivity(String taskId, ActivityImpl activityImpl,
			List<ActivityImpl> nextTaskList) throws Exception {
		List<ActivityImpl> rtnList = null;
		if (isJointTask(taskId)) {// 会签任务节点，不允许驳回
			rtnList = new ArrayList<ActivityImpl>();
		} else {
			rtnList = iteratorBackActivity(findProcessInstanceByTaskId(taskId), taskId, activityImpl,
					new ArrayList<ActivityImpl>(), new ArrayList<ActivityImpl>());
			rtnList.remove(activityImpl);
			rtnList.removeAll(nextTaskList);
		}
		return reverList(rtnList);
	}

	public boolean isJointTask(String taskId) {
		List<Task> tasks = taskService.createTaskQuery().taskId(taskId).taskDescription("jointProcessInit").list();
		return tasks.size() > 0;
	}

	/**
	 * 审批通过(驳回直接跳回功能需后续扩展)
	 * 
	 * @param taskId    当前任务ID
	 * @param variables 流程存储参数
	 * @throws Exception
	 */
	public void passProcess(String taskId, Map<String, Object> variables) throws Exception {
		List<Task> tasks = findJointProcessTask(taskId);
		for (Task task : tasks) {// 级联结束本节点发起的会签任务
			commitProcess(task.getId(), null, null);
		}
		commitProcess(taskId, variables, null);
	}

	/**
	 * 通过会签任务节点ID，查询会签子任务
	 */
	public List<Task> findJointProcessTask(String taskId) {
		String processInstanceId;
		try {
			processInstanceId = findProcessInstanceByTaskId(taskId).getId();
		} catch (Exception e) {
			processInstanceId = "";
		}
		List<Task> jpTasks = new ArrayList<Task>();
		if (!"".equals(processInstanceId)) {
			List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId)
					.taskDescription("jointProcess").list();
			for (Task task : tasks) {
				if (task.getParentTaskId().equals(taskId)) {
					jpTasks.add(task);
				}
			}
		}
		return jpTasks;
	}

	/**
	 * 驳回流程
	 * 
	 * @param taskId     当前任务ID
	 * @param activityId 驳回节点ID
	 * @param variables  流程存储参数
	 * @throws Exception
	 */
	public void backProcess(String taskId, String activityId, Map<String, Object> variables) throws Exception {
		if (StringUtil.isEmpty(activityId)) {
			throw new Exception("驳回目标节点ID为空！");
		}

		// 查询本节点发起的会签任务，并结束
		List<Task> tasks = findJointProcessTask(taskId);
		// List<Task> tasks = taskService.createTaskQuery().parentTaskId(taskId)
		// .taskDescription("jointProcess").list();
		for (Task task : tasks) {
			commitProcess(task.getId(), null, null);
		}

		// 查找所有并行任务节点，同时驳回
		List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(taskId).getId(),
				findTaskById(taskId).getTaskDefinitionKey());
		for (Task task : taskList) {
			commitProcess(task.getId(), variables, activityId);
		}
	}

	/**
	 * 取回流程
	 * 
	 * @param taskId     当前任务ID
	 * @param activityId 取回节点ID
	 * @throws Exception
	 */
	public void callBackProcess(String taskId, String activityId) throws Exception {
		if (StringUtil.isEmpty(activityId)) {
			throw new Exception("目标节点ID为空！");
		}

		// 查找所有并行任务节点，同时取回
		List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(taskId).getId(),
				findTaskById(taskId).getTaskDefinitionKey());
		for (Task task : taskList) {
			commitProcess(task.getId(), null, activityId);
		}
	}

	/**
	 * 中止流程(特权人直接审批通过等)
	 * 
	 * @param taskId
	 */
	public void endProcess(String taskId) throws Exception {
		ActivityImpl endActivity = findActivitiImpl(taskId, "end");
		commitProcess(taskId, null, endActivity.getId());
	}

	/**
	 * 会签操作
	 * 
	 * @param taskId    当前任务ID
	 * @param userCodes 会签人账号集合
	 * @throws Exception
	 */
	public void jointProcess(String taskId, List<String> userCodes) throws Exception {
		for (String userCode : userCodes) {
			TaskEntity task = (TaskEntity) taskService.newTask();
			task.setAssignee(userCode);
			task.setName(findTaskById(taskId).getName() + "-会签");
			task.setProcessDefinitionId(findProcessDefinitionEntityByTaskId(taskId).getId());
			task.setProcessInstanceId(findProcessInstanceByTaskId(taskId).getId());
			task.setParentTaskId(taskId);
			task.setDescription("jointProcess");
			taskService.saveTask(task);
		}
	}

	/**
	 * 转办流程
	 * 
	 * @param taskId   当前任务节点ID
	 * @param userCode 被转办人Code
	 */
	public void transferAssignee(String taskId, String userCode, Map<String, Object> variables) {
		for (String key : variables.keySet()) {
			taskService.setVariable(taskId, key, variables.get(key));
		}
		taskService.setAssignee(taskId, userCode);
	}

	/**
	 * ***************************************************************************************************************************************************<br>
	 * ************************************************以下为流程会签操作核心逻辑******************************************************************************<br>
	 * ***************************************************************************************************************************************************<br>
	 */

	/**
	 * ***************************************************************************************************************************************************<br>
	 * ************************************************以上为流程会签操作核心逻辑******************************************************************************<br>
	 * ***************************************************************************************************************************************************<br>
	 */

	/**
	 * ***************************************************************************************************************************************************<br>
	 * ************************************************以下为流程转向操作核心逻辑******************************************************************************<br>
	 * ***************************************************************************************************************************************************<br>
	 */

	/**
	 * @param taskId     当前任务ID
	 * @param variables  流程变量
	 * @param activityId 流程转向执行任务节点ID<br>
	 *                   此参数为空，默认为提交操作
	 * @throws Exception
	 */
	private void commitProcess(String taskId, Map<String, Object> variables, String activityId) throws Exception {
		if (variables == null) {
			variables = new HashMap<String, Object>();
		}
		// 跳转节点为空，默认提交操作
		if (StringUtil.isEmpty(activityId)) {
			taskService.complete(taskId, variables);
		} else {// 流程转向操作
			turnTransition(taskId, activityId, variables);
		}
	}

	/**
	 * 清空指定活动节点流向
	 * 
	 * @param activityImpl 活动节点
	 * @return 节点流向集合
	 */
	private List<PvmTransition> clearTransition(ActivityImpl activityImpl) {
		// 存储当前节点所有流向临时变量
		List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
		// 获取当前节点所有流向，存储到临时变量，然后清空
		List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
		for (PvmTransition pvmTransition : pvmTransitionList) {
			oriPvmTransitionList.add(pvmTransition);
		}
		pvmTransitionList.clear();

		return oriPvmTransitionList;
	}

	/**
	 * 还原指定活动节点流向
	 * 
	 * @param activityImpl         活动节点
	 * @param oriPvmTransitionList 原有节点流向集合
	 */
	private void restoreTransition(ActivityImpl activityImpl, List<PvmTransition> oriPvmTransitionList) {
		// 清空现有流向
		List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
		pvmTransitionList.clear();
		// 还原以前流向
		for (PvmTransition pvmTransition : oriPvmTransitionList) {
			pvmTransitionList.add(pvmTransition);
		}
	}

	/**
	 * 流程转向操作
	 * 
	 * @param taskId     当前任务ID
	 * @param activityId 目标节点任务ID
	 * @param variables  流程变量
	 * @throws Exception
	 */
	private void turnTransition(String taskId, String activityId, Map<String, Object> variables) throws Exception {
		// 当前节点
		ActivityImpl currActivity = findActivitiImpl(taskId, null);
		// 清空当前流向
		List<PvmTransition> oriPvmTransitionList = clearTransition(currActivity);

		// 创建新流向
		TransitionImpl newTransition = currActivity.createOutgoingTransition();
		// 目标节点
		ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);
		// 设置新流向的目标节点
		newTransition.setDestination(pointActivity);

		// 执行转向任务
		taskService.complete(taskId, variables);
		// 删除目标节点新流入
		pointActivity.getIncomingTransitions().remove(newTransition);

		// 还原以前流向
		restoreTransition(currActivity, oriPvmTransitionList);
	}

	/**
	 * ***************************************************************************************************************************************************<br>
	 * ************************************************以上为流程转向操作核心逻辑******************************************************************************<br>
	 * ***************************************************************************************************************************************************<br>
	 */

	/**
	 * ***************************************************************************************************************************************************<br>
	 * ************************************************以下为查询流程驳回节点核心逻辑***************************************************************************<br>
	 * ***************************************************************************************************************************************************<br>
	 */

	/**
	 * 迭代循环流程树结构，查询当前节点可驳回的任务节点
	 * 
	 * @param taskId       当前任务ID
	 * @param currActivity 当前活动节点
	 * @param rtnList      存储回退节点集合
	 * @param tempList     临时存储节点集合（存储一次迭代过程中的同级userTask节点）
	 * @return 回退节点集合
	 */
	private List<ActivityImpl> iteratorBackActivity(ProcessInstance processInstance, String taskId,
			ActivityImpl currActivity, List<ActivityImpl> rtnList, List<ActivityImpl> tempList) throws Exception {

		// 当前节点的流入来源
		List<PvmTransition> incomingTransitions = currActivity.getIncomingTransitions();
		// 条件分支节点集合，userTask节点遍历完毕，迭代遍历此集合，查询条件分支对应的userTask节点
		List<ActivityImpl> exclusiveGateways = new ArrayList<ActivityImpl>();
		// 并行节点集合，userTask节点遍历完毕，迭代遍历此集合，查询并行节点对应的userTask节点
		List<ActivityImpl> parallelGateways = new ArrayList<ActivityImpl>();
		// 遍历当前节点所有流入路径
		for (PvmTransition pvmTransition : incomingTransitions) {
			TransitionImpl transitionImpl = (TransitionImpl) pvmTransition;
			ActivityImpl activityImpl = transitionImpl.getSource();
			String type = (String) activityImpl.getProperty("type");
			/**
			 * 并行节点配置要求：<br>
			 * 必须成对出现，且要求分别配置节点ID为:XXX_start(开始)，XXX_end(结束)
			 */
			if ("parallelGateway".equals(type)) {// 并行路线
				String gatewayId = activityImpl.getId();
				String gatewayType = gatewayId.substring(gatewayId.lastIndexOf("_") + 1);
				if ("START".equals(gatewayType.toUpperCase())) {// 并行起点，停止递归
					return rtnList;
				} else {// 并行终点，临时存储此节点，本次循环结束，迭代集合，查询对应的userTask节点
					parallelGateways.add(activityImpl);
				}
			} else if ("startEvent".equals(type)) {// 开始节点，停止递归
				return rtnList;
			} else if ("userTask".equals(type)) {// 用户任务
				tempList.add(activityImpl);
			} else if ("exclusiveGateway".equals(type)) {// 分支路线，临时存储此节点，本次循环结束，迭代集合，查询对应的userTask节点
				currActivity = transitionImpl.getSource();
				exclusiveGateways.add(currActivity);
			}
		}

		/**
		 * 迭代条件分支集合，查询对应的userTask节点
		 */
		for (ActivityImpl activityImpl : exclusiveGateways) {
			iteratorBackActivity(processInstance, taskId, activityImpl, rtnList, tempList);
		}

		/**
		 * 迭代并行集合，查询对应的userTask节点
		 */
		for (ActivityImpl activityImpl : parallelGateways) {
			iteratorBackActivity(processInstance, taskId, activityImpl, rtnList, tempList);
		}

		/**
		 * 根据同级userTask集合，过滤最近发生的节点
		 */
		currActivity = filterNewestActivity(processInstance, rtnList, tempList);
		if (currActivity != null) {
			// 查询当前节点的流向是否为并行终点，并获取并行起点ID
			String id = findParallelGatewayId(currActivity);
			if (StringUtil.isEmpty(id)) {// 并行起点ID为空，此节点流向不是并行终点，符合驳回条件，存储此节点
				rtnList.add(currActivity);
			} else {// 根据并行起点ID查询当前节点，然后迭代查询其对应的userTask任务节点
				currActivity = findActivitiImpl(taskId, id);
			}

			// 清空本次迭代临时集合
			tempList.clear();

			iteratorBackActivity(processInstance, taskId, currActivity, rtnList, tempList);
		}
		return rtnList;
	}

	/**
	 * 反向排序list集合，便于驳回节点按顺序显示
	 * 
	 * @param list
	 * @return
	 */
	private List<ActivityImpl> reverList(List<ActivityImpl> list) {
		List<ActivityImpl> rtnList = new ArrayList<ActivityImpl>();
		// 由于迭代出现重复数据，排除重复
		for (int i = list.size(); i > 0; i--) {
			if (!rtnList.contains(list.get(i - 1)))
				rtnList.add(list.get(i - 1));
		}
		return rtnList;
	}

	/**
	 * 根据当前节点，查询输出流向是否为并行终点，如果为并行终点，则拼装对应的并行起点ID
	 * 
	 * @param activityImpl 当前节点
	 * @return
	 */
	private String findParallelGatewayId(ActivityImpl activityImpl) {
		List<PvmTransition> incomingTransitions = activityImpl.getOutgoingTransitions();
		for (PvmTransition pvmTransition : incomingTransitions) {
			TransitionImpl transitionImpl = (TransitionImpl) pvmTransition;
			activityImpl = transitionImpl.getDestination();
			String type = (String) activityImpl.getProperty("type");
			if ("parallelGateway".equals(type)) {// 并行路线
				String gatewayId = activityImpl.getId();
				String gatewayType = gatewayId.substring(gatewayId.lastIndexOf("_") + 1);
				if ("END".equals(gatewayType.toUpperCase())) {
					return gatewayId.substring(0, gatewayId.lastIndexOf("_")) + "_start";
				}
			}
		}
		return null;
	}

	/**
	 * 根据流入任务集合，查询最近一次的流入任务节点
	 * 
	 * @param processInstance 流程实例
	 * @param tempList        流入任务集合
	 * @return
	 */
	private ActivityImpl filterNewestActivity(ProcessInstance processInstance, List<ActivityImpl> rtnList,
			List<ActivityImpl> tempList) {
		while (tempList.size() > 0) {
			ActivityImpl activity_1 = tempList.get(0);
			if (rtnList.contains(activity_1)) {
				tempList.remove(activity_1);
				continue;
			}
			HistoricActivityInstance activityInstance_1 = findHistoricUserTask(processInstance, activity_1.getId());
			if (activityInstance_1 == null) {
				tempList.remove(activity_1);
				continue;
			}
			if (tempList.size() > 1) {
				ActivityImpl activity_2 = tempList.get(1);
				if (rtnList.contains(activity_2)) {
					tempList.remove(activity_2);
					continue;
				}
				HistoricActivityInstance activityInstance_2 = findHistoricUserTask(processInstance, activity_2.getId());
				if (activityInstance_2 == null) {
					tempList.remove(activity_2);
					continue;
				}

				if (activityInstance_1.getEndTime().before(activityInstance_2.getEndTime())) {
					tempList.remove(activity_1);
				} else {
					tempList.remove(activity_2);
				}
			} else {
				break;
			}
		}
		if (tempList.size() > 0) {
			return tempList.get(0);
		}
		return null;
	}

	/**
	 * 查询指定任务节点的最新记录
	 * 
	 * @param processInstance 流程实例
	 * @param activityId
	 * @return
	 */
	private HistoricActivityInstance findHistoricUserTask(ProcessInstance processInstance, String activityId) {
		HistoricActivityInstance rtnVal = null;
		// 查询当前流程实例审批结束的历史节点
		List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
				.activityType("userTask").processInstanceId(processInstance.getId()).activityId(activityId).finished()
				.orderByHistoricActivityInstanceEndTime().desc().list();
		if (historicActivityInstances.size() > 0) {
			rtnVal = historicActivityInstances.get(0);
		}

		return rtnVal;
	}

	/**
	 * *******************************************************************************************************<br>
	 * ********************************以上为查询流程驳回节点核心逻辑***********************************************<br>
	 * ********************************************************************************************************<br>
	 */

	/**
	 * ********************************************************************************<br>
	 * **********************以下为根据 任务节点ID 获取流程各对象查询方法**********************<br>
	 * *********************************************************************************<br>
	 */

	/**
	 * 根据任务ID获得任务实例
	 * 
	 * @param taskId 任务ID
	 * @return
	 * @throws Exception
	 */
	public TaskEntity findTaskById(String taskId) throws Exception {
		TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
		if (task == null) {
			throw new Exception("任务实例未找到!");
		}
		return task;
	}

	/**
	 * 根据流程实例ID和任务key值查询所有同级任务集合
	 * 
	 * @param processInstanceId
	 * @param key
	 * @return
	 */
	public List<Task> findTaskListByKey(String processInstanceId, String key) {
		return taskService.createTaskQuery().processInstanceId(processInstanceId).taskDefinitionKey(key).list();
	}

	/**
	 * 根据任务ID获取对应的流程实例
	 * 
	 * @param taskId 任务ID
	 * @return
	 * @throws Exception
	 */
	public ProcessInstance findProcessInstanceByTaskId(String taskId) throws Exception {
		// 找到流程实例
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(findTaskById(taskId).getProcessInstanceId()).singleResult();
		if (processInstance == null) {
			throw new Exception("流程实例未找到!");
		}
		return processInstance;
	}

	/**
	 * 根据任务ID获取流程定义
	 * 
	 * @param taskId 任务ID
	 * @return
	 * @throws Exception
	 */
	public ProcessDefinitionEntity findProcessDefinitionEntityByTaskId(String taskId) throws Exception {
		// 取得流程定义
		ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(findTaskById(taskId).getProcessDefinitionId());
		if (processDefinition == null) {
			throw new Exception("流程定义未找到!");
		}
		return processDefinition;
	}

	public ProcessDefinitionEntity findProcessDefinitionEntityById(String processDefinitionId) throws Exception {
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(processDefinitionId);
		if (processDefinitionEntity == null) {
			throw new Exception("流程定义未找到!");
		}
		return processDefinitionEntity;
	}

	/**
	 * 根据任务ID和节点ID获取活动节点 <br>
	 * 
	 * @param taskId     任务ID
	 * @param activityId 活动节点ID <br>
	 *                   如果为null或""，则默认查询当前活动节点 <br>
	 *                   如果为"end"，则查询结束节点 <br>
	 * 
	 * @return
	 * @throws Exception
	 */
	public ActivityImpl findActivitiImpl(String taskId, String activityId) throws Exception {
		// 取得流程定义
		ProcessDefinitionEntity processDefinition = findProcessDefinitionEntityByTaskId(taskId);

		// 获取当前活动节点ID
		if (StringUtil.isEmpty(activityId)) {
			activityId = findTaskById(taskId).getTaskDefinitionKey();
		}

		// 根据流程定义，获取该流程实例的结束节点
		if (activityId.toUpperCase().equals("END")) {
			for (ActivityImpl activityImpl : processDefinition.getActivities()) {
				List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
				if (pvmTransitionList.isEmpty()) {
					return activityImpl;
				}
			}
		}

		// 根据节点ID，获取对应的活动节点
		ActivityImpl activityImpl = ((ProcessDefinitionImpl) processDefinition).findActivity(activityId);

		return activityImpl;
	}

	/**
	 * ********************************************************************************<br>
	 * **********************以上为根据 任务节点ID 获取流程各对象查询方法**********************<br>
	 * *********************************************************************************<br>
	 */

	/**
	 * 查询流程定义对象
	 * 
	 * @throws Exception
	 */
	public ProcessDefinition getProcessDefinition(String processDefinitionId) throws Exception {
		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId);
		List<ProcessDefinition> list = query.list();
		if (list == null || list.size() == 0) {
			throw new Exception("流程定义未找到!");
		}
		return list.get(0);
	}

	public ProcessDefinition getProcessDefinitionByKey(String processDefinitionKey) throws Exception {
		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery()
				.processDefinitionKey(processDefinitionKey);
		List<ProcessDefinition> list = query.list();
		if (list == null || list.size() == 0) {
			throw new Exception("流程定义未找到!");
		}
		return list.get(0);
	}

	/**
	 * 查询流程启动实例
	 * 
	 * @throws Exception
	 */
	public ProcessInstance getProcessInstance(String processInstanceId) throws Exception {
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		if (processInstance == null) {
			throw new Exception("流程实例未找到!");
		}
		return processInstance;
	}

	public List<HistoricTaskInstance> findHistoryTask(String processInstanceId) {
		return historyService.createHistoricTaskInstanceQuery()// 创建历史任务实例查询
				.processInstanceId(processInstanceId)//
				.orderByTaskCreateTime().asc().list();
	}

	public ActivityImpl getActivity(String processDefId, String activityId) throws Exception {
		ProcessDefinitionEntity pde = findProcessDefinitionEntityById(processDefId);
		return pde.findActivity(activityId);
	}

	/**
	 * 获取下一个用户任务用户组信息
	 * 
	 * @throws Exception
	 */
	@Override
	public TaskDefinition getNextTaskDefinition(String taskId) throws Exception {
		String id = null;
		TaskDefinition task = null;
		ProcessDefinitionEntity processDefinitionEntity = null;

		// 获取流程实例Id信息
		String processInstanceId = taskService.createTaskQuery().taskId(taskId).singleResult().getProcessInstanceId();

		// 获取流程发布Id信息
		String definitionId = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId)
				.singleResult().getProcessDefinitionId();

		processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(definitionId);

		// 获取当前活动节点ID
		String activityId = findTaskById(taskId).getTaskDefinitionKey();

		List<ActivityImpl> activitiList = processDefinitionEntity.getActivities();

		// 遍历所有节点信息
		for (ActivityImpl activityImpl : activitiList) {
			id = activityImpl.getId();
			if (activityId.equals(id)) {
				// 获取下一个节点信息
				task = nextTaskDefinition(activityImpl, activityImpl.getId(), null, processInstanceId);
				break;
			}
		}
		return task;
	}

	/**
	 * 下一个任务节点信息, 如果下一个节点为用户任务则直接返回, 如果下一个节点为排他网关, 获取排他网关Id信息,
	 * 根据排他网关Id信息和execution获取流程实例排他网关Id为key的变量值, 根据变量值分别执行排他网关后线路中的el表达式,
	 * 并找到el表达式通过的线路后的用户任务
	 * 
	 * @param ActivityImpl activityImpl 流程节点信息
	 * @param String       activityId 当前流程节点Id信息
	 * @param String       elString 排他网关顺序流线段判断条件
	 * @param String       processInstanceId 流程实例Id信息
	 * @return
	 */
	private TaskDefinition nextTaskDefinition(ActivityImpl activityImpl, String activityId, String elString,
			String processInstanceId) {

		PvmActivity ac = null;

		Object s = null;

		// 如果遍历节点为用户任务并且节点不是当前节点信息
		if ("userTask".equals(activityImpl.getProperty("type")) && !activityId.equals(activityImpl.getId())) {
			// 获取该节点下一个节点信息
			TaskDefinition taskDefinition = ((UserTaskActivityBehavior) activityImpl.getActivityBehavior())
					.getTaskDefinition();
			return taskDefinition;
		} else if ("exclusiveGateway".equals(activityImpl.getProperty("type"))) {// 当前节点为exclusiveGateway
			List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
			// outTransitionsTemp = ac.getOutgoingTransitions();

			// 如果网关路线判断条件为空信息
//          if (StringUtils.isEmpty(elString)) {
			// 获取流程启动时设置的网关判断条件信息
			elString = getGatewayCondition(activityImpl.getId(), processInstanceId);
//          }
			// 如果排他网关只有一条线路信息
			if (outTransitions.size() == 1) {
				return nextTaskDefinition((ActivityImpl) outTransitions.get(0).getDestination(), activityId, elString,
						processInstanceId);
			} else if (outTransitions.size() > 1) { // 如果排他网关有多条线路信息
				for (PvmTransition tr1 : outTransitions) {
					s = tr1.getProperty("conditionText"); // 获取排他网关线路判断条件信息
					// 判断el表达式是否成立
					if (isCondition(activityImpl.getId(), s.toString().trim(), elString)) {
						return nextTaskDefinition((ActivityImpl) tr1.getDestination(), activityId, elString,
								processInstanceId);
					}

				}
			}
		} else {
			// 获取节点所有流向线路信息
			List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
			List<PvmTransition> outTransitionsTemp = null;
			for (PvmTransition tr : outTransitions) {
				ac = tr.getDestination(); // 获取线路的终点节点
				// 如果流向线路为排他网关
				if ("exclusiveGateway".equals(ac.getProperty("type"))) {
					outTransitionsTemp = ac.getOutgoingTransitions();

					// 如果网关路线判断条件为空信息
					if (StringUtil.isEmpty(elString)) {
						// 获取流程启动时设置的网关判断条件信息
						elString = getGatewayCondition(ac.getId(), processInstanceId);
					}

					// 如果排他网关只有一条线路信息
					if (outTransitionsTemp.size() == 1) {
						return nextTaskDefinition((ActivityImpl) outTransitionsTemp.get(0).getDestination(), activityId,
								elString, processInstanceId);
					} else if (outTransitionsTemp.size() > 1) { // 如果排他网关有多条线路信息
						for (PvmTransition tr1 : outTransitionsTemp) {
							s = tr1.getProperty("conditionText"); // 获取排他网关线路判断条件信息
							// 判断el表达式是否成立
							if (isCondition(ac.getId(), s.toString().trim(), elString)) {
								return nextTaskDefinition((ActivityImpl) tr1.getDestination(), activityId, elString,
										processInstanceId);
							}
						}
					}
				} else if ("userTask".equals(ac.getProperty("type"))) {
					return ((UserTaskActivityBehavior) ((ActivityImpl) ac).getActivityBehavior()).getTaskDefinition();
				} else {
				}
			}
			return null;
		}
		return null;
	}

	/**
	 * 查询流程启动时设置排他网关判断条件信息
	 * 
	 * @param String gatewayId 排他网关Id信息, 流程启动时设置网关路线判断条件key为网关Id信息
	 * @param String processInstanceId 流程实例Id信息
	 * @return
	 */
	public String getGatewayCondition(String gatewayId, String processInstanceId) {
		Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).singleResult();
		Object object = runtimeService.getVariable(execution.getId(), gatewayId);
		return object == null ? "" : object.toString();
	}

	/**
	 * 根据key和value判断el表达式是否通过信息
	 * 
	 * @param String key el表达式key信息
	 * @param String el el表达式信息
	 * @param String value el表达式传入值信息
	 * @return
	 */
	public boolean isCondition(String key, String el, String value) {
		ExpressionFactory factory = new ExpressionFactoryImpl();
		SimpleContext context = new SimpleContext();
		context.setVariable(key, factory.createValueExpression(value, String.class));
		ValueExpression e = factory.createValueExpression(context, el, boolean.class);
		return (Boolean) e.getValue(context);
	}

	/**
	 * 获取下一个用户任务信息
	 * 
	 * @param String taskId 任务Id信息
	 * @return 下一个用户任务用户组信息
	 * @throws Exception
	 */
	public List<ActivityImpl> getNextTaskInfo(String taskId) {
		try {
			ActivityImpl activityImpl = findActivitiImpl(taskId, null);
			List<ActivityImpl> nextTaskList = getNextTaskInfo(activityImpl);
			return nextTaskList;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<ActivityImpl> getNextTaskInfo(ActivityImpl activityImpl) {
		try {
			if (activityImpl != null) {
				List<ActivityImpl> nextTaskList = nextTaskDefinition(activityImpl, activityImpl.getId());
				return nextTaskList;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取所有下一节点
	 * 
	 * @param activityImpl 流程节点信息
	 * @param taskId       任务ID
	 * @return 所有下一节的节点定义信息
	 * @throws Exception
	 */
	public List<TaskDefinition> getNextTaskDefinitionList(ActivityImpl activityImpl, String taskId) throws Exception {
		List<TaskDefinition> taskDefinitionList = new ArrayList<TaskDefinition>();// 所有的任务实例
		List<TaskDefinition> nextTaskDefinition = new ArrayList<TaskDefinition>();// 逐个获取的任务实例
		TaskDefinition taskDefinition = null;
		String activityId = findTaskById(taskId).getTaskDefinitionKey();
		if ("userTask".equals(activityImpl.getProperty("type")) && !activityId.equals(activityImpl.getId())) {
			taskDefinition = ((UserTaskActivityBehavior) activityImpl.getActivityBehavior()).getTaskDefinition();
			taskDefinitionList.add(taskDefinition);
		} else {
			List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
			List<PvmTransition> outTransitionsTemp = null;
			for (PvmTransition tr : outTransitions) {
				PvmActivity ac = tr.getDestination(); // 获取线路的终点节点
				// 如果是互斥网关或者是并行网关
				if ("exclusiveGateway".equals(ac.getProperty("type"))
						|| "parallelGateway".equals(ac.getProperty("type"))) {
					outTransitionsTemp = ac.getOutgoingTransitions();
					if (outTransitionsTemp.size() == 1) {
						nextTaskDefinition = getNextTaskDefinitionList(
								(ActivityImpl) outTransitionsTemp.get(0).getDestination(), activityId);
						taskDefinitionList.addAll(nextTaskDefinition);
					} else if (outTransitionsTemp.size() > 1) {
						for (PvmTransition tr1 : outTransitionsTemp) {
							nextTaskDefinition = getNextTaskDefinitionList((ActivityImpl) tr1.getDestination(),
									activityId);
							taskDefinitionList.addAll(nextTaskDefinition);
						}
					}
				} else if ("userTask".equals(ac.getProperty("type"))) {
					taskDefinition = ((UserTaskActivityBehavior) ((ActivityImpl) ac).getActivityBehavior())
							.getTaskDefinition();
					taskDefinitionList.add(taskDefinition);
				} else {
					LogUtil.debug((String) ac.getProperty("type"));
				}
			}
		}
		return taskDefinitionList;
	}

	/**
	 * 下一个任务节点信息, 如果下一个节点为用户任务则直接返回, 如果下一个节点为排他网关, 获取排他网关Id信息, 根据排他网关Id信息获取下面的节点
	 * 
	 * @param ActivityImpl activityImpl 流程节点信息
	 * @param String       activityId 当前流程节点Id信息
	 * @param String       processInstanceId 流程实例Id信息
	 * @return
	 */
	public List<ActivityImpl> nextTaskDefinition(ActivityImpl activityImpl, String activityId) {

		PvmActivity ac = null;

		List<ActivityImpl> taskList = new ArrayList<ActivityImpl>();
		// 如果遍历节点为用户任务并且节点不是当前节点信息
		if (("userTask".equals(activityImpl.getProperty("type")) || "endEvent".equals(activityImpl.getProperty("type")))
				&& !activityId.equals(activityImpl.getId())) {
			taskList.add(activityImpl);

		} else {
			// 获取节点所有流向线路信息
			List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
			for (PvmTransition tr : outTransitions) {
				ac = tr.getDestination(); // 获取线路的终点节点
				// 如果流向线路为排他网关
				if ("exclusiveGateway".equals(ac.getProperty("type"))) {

					for (PvmTransition tr1 : ac.getOutgoingTransitions()) {
						List<ActivityImpl> tmpList = nextTaskDefinition((ActivityImpl) tr1.getDestination(),
								activityId);
						taskList.addAll(tmpList);
					}
				} else if ("userTask".equals(ac.getProperty("type")) || "endEvent".equals(ac.getProperty("type"))) {
					taskList.add((ActivityImpl) ac);
				}
			}
		}
		return taskList;
	}

	public List<PvmTransition> getNextTaskInPvm(List<ActivityImpl> nextTaskList, String taskId) {
		try {
			ActivityImpl activityImpl = findActivitiImpl(taskId, null);
			return getNextTaskInPvm(nextTaskList, activityImpl);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<PvmTransition> getNextTaskInPvm(List<ActivityImpl> nextTaskList, ActivityImpl activityImpl) {
		try {
			if (activityImpl != null) {
				List<PvmTransition> list = getNextTaskInPvmTransition(nextTaskList, activityImpl);
				Collections.sort(list, new Comparator<PvmTransition>() {
					public int compare(PvmTransition arg0, PvmTransition arg1) {
						return arg0.getId().compareTo(arg1.getId());
					}
				});
				return list;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * @param nextTaskList 下一节点集合
	 * @param activity     当前节点
	 * @return 下一节点的连线
	 */
	public List<PvmTransition> getNextTaskInPvmTransition(List<ActivityImpl> nextTaskList, ActivityImpl activityImpl) {

		PvmActivity ac = null;
		List<PvmTransition> listPvm = new ArrayList<PvmTransition>();

		for (PvmTransition tr : activityImpl.getOutgoingTransitions()) {
			ac = tr.getDestination(); // 获取线路的终点节点

			if ("userTask".equals(ac.getProperty("type")) || "endEvent".equals(ac.getProperty("type"))) {
				if (nextTaskList.contains((ActivityImpl) ac)) {
					listPvm.add(tr);
				}
			} else {
				if ("exclusiveGateway".equals(ac.getProperty("type"))) {
					List<PvmTransition> tmpList = getNextTaskInPvm(nextTaskList, (ActivityImpl) ac);
					listPvm.addAll(tmpList);
				}
			}
		}
		return listPvm;
	}

	/**
	 * 查找第一个节点
	 * @param processDefinitionId
	 * @return
	 */
	public PvmActivity findFirstActivity(String processDefinitionId) {
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(processDefinitionId);
		ActivityImpl startActivity = processDefinitionEntity.getInitial();
		PvmTransition pvmTransition = startActivity.getOutgoingTransitions().get(0);
		PvmActivity targetActivity = pvmTransition.getDestination();
		String startType = startActivity.getProperty("type").toString();
		 if (!"userTask".equals(startType)) {
			return targetActivity;
		}
		return null;
	}
}